import {ShapeFlags} from "../shared/ShapeFlags";

// 标记Fragment类型的组件
export const Fragment = Symbol("Fragment");
export const Text = Symbol("Text");
// type类型的布尔值，用于虚拟节点的类型判断
//  如果是一个字符串，那么就是一个html元素，否则就是一个有状态的组件。
//  有状态的组件就是用户写的带data,或者setup 属性的对象
function getShapeFlags(type) {
//
    return typeof type === 'string' ? ShapeFlags.ELEMENT : ShapeFlags.STATEFUL_COMPONENT
}

/**
 * 创建虚拟节点.
 * @param type  虚拟节点的类型,可能是对象(组件)或者字符串(html元素)
 *              一开始的一般是一个组件,最后的一定是一个div 元素.
 * @param props
 * @param children
 */
export function createVNode(type, props?, children?) {
    /**
     *  component  保存组件实例本身,赋值发生在创建组件实例的时候
     */
    const vnode = {
        type,
        props,
        children,
        component: null,
        next: null,
        key: props && props.key,
        shapeFlags: getShapeFlags(type),
        el: null
    }
    // 增加子类型相关的标志位,两者是可以共存的.
    // 使用 | 位运算符来赋值
    if (typeof children === 'string') {
        vnode.shapeFlags |= ShapeFlags.TEXT_CHILDREN
    } else if (Array.isArray(children)) {
        vnode.shapeFlags |= ShapeFlags.ARRAY_CHILDREN
    }
    // 使用&位运算符来判断，如果大于1会被强转成true
    // 如果vnode是有状态的组件类型,并且子组件是对象类型,才需要做插槽的处理
    if (vnode.shapeFlags & ShapeFlags.STATEFUL_COMPONENT) {
        if (typeof children === 'object') {
            vnode.shapeFlags |= ShapeFlags.SLOT_CHILDREN
        }
    }

    return vnode;
}

export function createTextVnode(text: string) {
    return createVNode(Text, {}, text);

}